package com.example.beidouapplication;

import java.util.concurrent.TimeUnit;



public class serbuf {

    static int BufferSize = 4096;

    volatile byte[] InBuf, OutBuf;
    volatile int buf_len;
    volatile int pInFront, pInRear, pOutFront, pOutRear;
    volatile boolean InOverflow, InUnderflow, OutOverflow, OutUnderflow;
//    volatile SerialPort serialPort;

    static void delay(int time) {
        try {
            TimeUnit.MICROSECONDS.sleep(time);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    serbuf(int buf_size) {
        InBuf = new byte[buf_size];
        OutBuf = new byte[buf_size];
        buf_len = buf_size;
    }

    void sendstring(char[] data) {
//        serialPort.
    }


    serbuf() {
        this(BufferSize);
    }

    synchronized void WriteInBuf(byte elem) {
        InBuf[pInFront++] = elem;
        if (pInFront >= buf_len) {
            pInFront = 0;
        }
        if (pInFront == pInRear) {
            InOverflow = true;
        }
    }


    synchronized void pt_In_Align() {
        if (InOverflow) {
            pInRear = pInFront;
        }
    }

    synchronized void WriteOutBuf(byte elem) {
        OutBuf[pOutFront++] = elem;
        if (pOutFront >= buf_len) {
            pOutFront = 0;
        }
        if (pOutFront == pOutRear) {
            OutOverflow = true;
        }
    }

    synchronized void pt_Out_Align() {
        if (OutOverflow) {
            pOutRear = pOutFront;
        }
    }

    int ReadInBuf(byte[] out_buf) {
        int bytes = 0;

        while (pInRear != pInFront || InOverflow) {
            if (InOverflow) {
                InOverflow = false;
            }
            out_buf[bytes++] = InBuf[pInRear++];
            if (pInRear >= buf_len) {
                pInRear = 0;
            }
        }
        return bytes;
    }

    int ReadOutBuf(byte[] out_buf) {
        int bytes = 0;

        while (pOutRear != pOutFront || OutOverflow) {
            if (OutOverflow) {
                OutOverflow = false;
            }
            out_buf[bytes++] = OutBuf[pOutRear++];
            if (pOutRear >= buf_len) {
                pOutRear = 0;
            }
            if (bytes >= 16) {
                break;
            }
        }

        return bytes;
    }
}

class COM1_Buf extends serbuf {
    volatile byte[] FrameIn, DataIn, FrameOut, DataOut;
    volatile boolean frameOn, RcvOk, judge;
    volatile int frameLen, count, frameInLen, dataInLen;

    COM1_Buf(int buf_size) {
        super(buf_size);

        frameOn = false;
        judge = false;
        RcvOk = true;
        frameLen = 512;
        dataInLen = 0;
        count = 0;
        FrameIn = new byte[frameLen];
        DataIn = new byte[frameLen];
        FrameOut = new byte[frameLen];
        DataOut = new byte[frameLen];
    }

    COM1_Buf() {
        super();

        frameOn = false;
        judge = false;
        RcvOk = true;
        frameLen = 512;                                                                //2.1协议中说一条语句中的字符数最多为300个。
        count = 0;
        dataInLen = 0;
        FrameIn = new byte[frameLen];
        DataIn = new byte[frameLen];
        FrameOut = new byte[frameLen];
        DataOut = new byte[frameLen];
        DataOut[0] = 0x7e;
        DataOut[frameLen - 1] = 0x7e;
    }

    synchronized void WriteInBufArray(byte[] elem) {
        for (byte e : elem) {
            WriteInBuf(e);
        }
        pt_In_Align();
    }

    int GetFrame() {
        int checksum = 0;
        int check_low = 0;
        int check_hig = 0;
        while (pInRear != pInFront || InOverflow) {
            FrameIn[count] = InBuf[pInRear++];
            if (InOverflow) InOverflow = false;
            if (pInRear >= buf_len)
                pInRear = 0;
            if (pInRear == pInFront) {
                //
                delay(40);        //防止访问GetFrame()太快,InBuf来不及收到完整数据.
            }

            if (FrameIn[count] == 0x24) {
                judge = true;
            }
            if (FrameIn[count] == 0x2A) {
                if (judge)                                                        //有尾*,有头$
                {
                    for (int i = 1; i < count; i++) {
                        checksum ^= FrameIn[i];
                    }
                    checksum = checksum & 0xff;                  //将16进制的高4位和低4位转换成两个ASCII字符，（0-9，A-F）。最高有效位首先发送。
                    check_low = checksum & 0x0f;
                    check_hig = (checksum >> 4) & 0x0f;
                    if (check_low <= 9)
                        check_low = check_low + 0x30;
                    else
                        check_low = check_low + 0x37;
                    if (check_hig <= 9)
                        check_hig = check_hig + 0x30;
                    else
                        check_hig = check_hig + 0x37;

                    count = count + 1;
                    FrameIn[count] = InBuf[pInRear++];
                    count = count + 1;
                    FrameIn[count] = InBuf[pInRear++];
                    FrameIn[count] = (byte) check_low;
                    FrameIn[count - 1] = (byte) check_hig;
                    if ((FrameIn[count] == check_low) && (FrameIn[count - 1] == check_hig))        //有头$,有尾*,且校验正确
                    {
                        frameOn = true;
                        break;
                    } else                                                                                                                            //有头$,有尾*,但校验不正确,则重新找头$
                    {
                        judge = false;
                        count = 0;
                    }
                } else                                                                //有尾*,没有头$,则重新找头$
                {
                    judge = false;
                    count = 0;
                }
            }
            if (judge) {
                if (FrameIn[count] == 0x24) count = 0;            //又发现$后,count为0,后面的$算开头.
                count++;                                                            //发现$后,count才增加数值.
            }
        }
        if (!frameOn)                                            //读完缓存区,也没找到正确帧,则放弃.
        {
            count = 0;
            judge = false;
        }
        return count;
    }

    int Decoding() {
        if (!frameOn && count > 0) {
            int i = 0, j = 0;
            for (; i < count; i++) {
                if (FrameIn[i] == 0x40) {
                    if (FrameIn[i + 1] == 0xc0)
                        DataIn[j++] = (byte) (FrameIn[++i] & 0x7f);
                    else if (FrameIn[i + 1] == 0xfe)
                        DataIn[j++] = (byte) (FrameIn[++i] & 0x7f);
                    else
                        DataIn[j++] = FrameIn[i];        /*除了校验帧,应该不会出现这种情况*/
                } else {
                    DataIn[j++] = FrameIn[i];
                }
            }
            count = 0;
            return j;
        } else
            return 0;
    }

    int Encoding() {
        int i = 0, j = 0;
        for (; i < frameLen; i++) {
            if (i == 0 || i == frameLen - 1) {
                FrameOut[j++] = DataOut[i];        //=0x7e
            } else if (DataOut[i] == 0x40 || DataOut[i] == 0x7e)    /*帧校验也算上了*/ {
                FrameOut[j++] = 0x40;
                FrameOut[j++] = (byte) (DataOut[i] | 0x80);
            } else {
                FrameOut[j++] = DataOut[i];
            }
        }
        return j;

    }

    int GetData(byte[] in_buf) {
        int bytes = 0;
        GetFrame();
        if (frameOn) {
            bytes = count + 1;
            for (int i = 0; i < bytes; i++) {
                in_buf[i] = FrameIn[i];
            }
            frameOn = false;
            count = 0;
            judge = false;
        }
        return bytes;
    }

    int PutFrame() {
        int bytes;
        bytes = Encoding();
        for (int i = 0; i < bytes; i++) {
            WriteOutBuf(FrameOut[i]);
        }
        pt_Out_Align();

        return 0;
    }

    int PutData(byte[] out_buf, int num) {
        for (int i = 0; i < num; i++) {
            DataOut[i] = out_buf[i];
        }
        return 0;
    }

    byte GetRcvFlag() {
        if (RcvOk) {
            return 0x06;
        } else {
            return 0x15;
        }
    }
}

class COM3_Buf extends serbuf {
    static int COM3_Data_Out_Len = 64;

    volatile byte[] FrameIn, DataIn, FrameOut, DataOut;
    boolean frameOn;
    volatile int frameLen, count, frameInLen, dataInLen;


    COM3_Buf(int buf_size) {
        super(buf_size);

        frameOn = false;
        frameLen = COM3_Data_Out_Len;
        count = 0;
        FrameIn = new byte[frameLen * 2];
        DataIn = new byte[frameLen];
        FrameOut = new byte[frameLen * 2];
        DataOut = new byte[frameLen];
    }

    COM3_Buf() {
        super();

        frameOn = false;
        frameLen = COM3_Data_Out_Len;
        count = 0;
        FrameIn = new byte[frameLen * 2];
        DataIn = new byte[frameLen];
        FrameOut = new byte[frameLen * 2];
        DataOut = new byte[frameLen];
    }

    synchronized void WriteInBufArray(byte[] elem) {
        int i = elem.length;
        int l = 0;
        while (i > l) {
            boolean over = false;
            int r = l + 7;
            if (elem[l] == (byte) 0xca && r < i) {
                over = true;
            } else if (elem[l] == (byte) 0xfe && r < i) {
                over = true;

            } else if (elem[l] == (byte) 0xfd && r < i) {
                over = true;

            } else if (elem[l] == (byte) 0xfc && l + 15 < i) {
                over = true;
                r = l + 15;

            } else if (elem[l] == (byte) 0xfb && r < i) {
                over = true;

            } else if (elem[l] == (byte) 0xec && r < i) {
                over = true;
            } else if (elem[l] == (byte) 0xeb && r < i) {
                over = true;
            } else if (elem[l] == (byte) 0xe7 && r < i) {
                over = true;
            } else if (elem[l] == (byte) 0xaa && r < i) {
                over = true;
            } else {
                r = l;
            }
            if (r < i && (r - l + 1) % 8 == 0 && over) {
                WriteInBuf((byte) 0x7e);
                for (int j = l; j <= r; j++) {
                    WriteInBufTran(elem[j]);
                }
                WriteInBuf((byte) 0x7e);
                pt_In_Align();
            } else {
//                continue;
            }
            l = r + 1;
        }
//        if (over && (i % 8) == 0) {
//
//            WriteInBuf((byte) 0x7e);
//            for (byte e : elem) {
//                WriteInBufTran(e);
//            }
//            WriteInBuf((byte) 0x7e);
//            pt_In_Align();
//        }

    }

    synchronized int GetFrame() {
        int bytes = 0;

        while (pInRear != pInFront || InOverflow) {
            if (InOverflow) {
                InOverflow = false;
            }
            FrameIn[count] = InBuf[pInRear++];
            if (pInRear >= buf_len) {
                pInRear = 0;
            }

            if (!frameOn && FrameIn[count] == 0x7e) {
                frameOn = true;
                count++;
                bytes++;
            } else if (frameOn) {
                if (FrameIn[count] == 0x7e) {
                    frameOn = false;
                    count++;
                    bytes++;
                    break;
                } else {
                    count++;
                    bytes++;
                }
            } else {
            }
        }
        return bytes;
    }

    int Decoding() {
        if (!frameOn && count > 0) {
            int i = 0, j = 0;
            for (; i < count; i++) {
                if (FrameIn[i] == 0x40) {
                    if (FrameIn[i + 1] == (byte)(0xc0))
                        DataIn[j++] = (byte) (FrameIn[++i] & 0x7f);
                    else if (FrameIn[i + 1] == (byte) 0xfe)
                        DataIn[j++] = (byte) (FrameIn[++i] & 0x7f);
                    else
                        DataIn[j++] = FrameIn[i];
                } else {
                    DataIn[j++] = FrameIn[i];
                }
            }
            count = 0;
            return j;
        } else
            return 0;
    }

    int Encoding() {
        int i = 0, j = 0;
        for (; i < frameLen; i++) {
            if (i == 0 || i == frameLen - 1) {
                FrameOut[j++] = DataOut[i];        //=0x7e
            } else if (DataOut[i] == 0x40 || DataOut[i] == 0x7e) {
                FrameOut[j++] = 0x40;
                FrameOut[j++] = (byte) (DataOut[i] | 0x80);
            } else {
                FrameOut[j++] = DataOut[i];
            }
        }

        return j;

    }

    int PutFrame() {
        int bytes;

        bytes = Encoding();
        for (int i = 0; i < bytes; i++) {
            WriteOutBuf(FrameOut[i]);
        }
        pt_Out_Align();

        return 0;
    }

    int PutData(byte[] out_buf, int num) {
        for (int i = 0; i < num; i++) {
            WriteOutBuf(out_buf[i]);
        }
        pt_Out_Align();
        return 0;
    }

    synchronized void WriteInBufTran(byte elem) {
        if (elem == 0x7e || elem == 0x40) {
            InBuf[pInFront++] = 0x40;
            if (pInFront >= buf_len) {
                pInFront = 0;
            }
            if (pInFront == pInRear) {
                InOverflow = true;
            }
            InBuf[pInFront++] = (byte) (elem | 0x80);
        } else {
            InBuf[pInFront++] = elem;
        }
        if (pInFront >= buf_len) {
            pInFront = 0;
        }
        if (pInFront == pInRear) {
            InOverflow = true;
        }
    }

    synchronized int InDataProc(byte[] in_buf) {
        int bytes;

        GetFrame();
        bytes = Decoding();
        if (bytes > 0) {
            for (int i = 0; i < bytes - 2; i++) {
                in_buf[i] = DataIn[i + 1];
            }
            return bytes - 2;
        } else {
            return bytes;
        }
    }
}


class COM4_Buf extends serbuf {
    volatile byte[] FrameIn, DataIn, FrameOut, DataOut;
    volatile boolean frameOn, RcvOk, judge;
    volatile int frameLen, count, frameInLen, dataInLen;

    COM4_Buf(int buf_size) {
        super(buf_size);

        frameOn = false;
        judge = false;
        RcvOk = true;
        frameLen = 512;
        dataInLen = 0;
        count = 0;
        FrameIn = new byte[frameLen];
        DataIn = new byte[frameLen];
        FrameOut = new byte[frameLen];
        DataOut = new byte[frameLen];
    }

    COM4_Buf() {
        super();

        frameOn = false;
        judge = false;
        RcvOk = true;
        frameLen = 512;                                                                //2.1协议中说一条语句中的字符数最多为300个。
        count = 0;
        dataInLen = 0;
        FrameIn = new byte[frameLen];
        DataIn = new byte[frameLen];
        FrameOut = new byte[frameLen];
        DataOut = new byte[frameLen];
    }


    synchronized int GetFrame() {
        int checksum = 0;
        int check_low = 0;
        int check_hig = 0;
        while (pInRear != pInFront || InOverflow) {
            FrameIn[count] = InBuf[pInRear++];
            if (InOverflow) InOverflow = false;
            if (pInRear >= buf_len)
                pInRear = 0;
            if (pInRear == pInFront) {
                delay(40);        //防止访问GetFrame()太快,InBuf来不及收到完整数据.
            }

            if (FrameIn[count] == 0x24) judge = true;
            if (FrameIn[count] == 0x2A) {
                if (judge)                                                        //有尾*,有头$
                {
                    for (int i = 1; i < count; i++) {
                        checksum ^= FrameIn[i];
                    }
                    checksum = checksum & 0xff;                  //将16进制的高4位和低4位转换成两个ASCII字符，（0-9，A-F）。最高有效位首先发送。
                    check_low = checksum & 0x0f;
                    check_hig = (checksum >> 4) & 0x0f;
                    if (check_low <= 9)
                        check_low = check_low + 0x30;
                    else
                        check_low = check_low + 0x37;
                    if (check_hig <= 9)
                        check_hig = check_hig + 0x30;
                    else
                        check_hig = check_hig + 0x37;

                    count = count + 1;
                    FrameIn[count] = InBuf[pInRear++];
                    count = count + 1;
                    FrameIn[count] = InBuf[pInRear++];
                    FrameIn[count] = (byte) check_low;
                    FrameIn[count - 1] = (byte) check_hig;
                    if ((FrameIn[count] == check_low) && (FrameIn[count - 1] == check_hig))        //有头$,有尾*,且校验正确
                    {
                        frameOn = true;
                        break;
                    } else                                                                                                                            //有头$,有尾*,但校验不正确,则重新找头$
                    {
                        judge = false;
                        count = 0;
                    }
                } else                                                                //有尾*,没有头$,则重新找头$
                {
                    judge = false;
                    count = 0;
                }
            }
            if (judge) {
                if (FrameIn[count] == 0x24) count = 0;            //又发现$后,count为0,后面的$算开头.
                count++;                                                            //发现$后,count才增加数值.
            }
        }
        if (!frameOn)                                            //读完缓存区,也没找到正确帧,则放弃.
        {
            count = 0;
            judge = false;
        }
        return count;
    }

    synchronized void WriteInBufArray(byte[] elem) {
        for (byte e : elem) {
            WriteInBuf(e);
        }
        pt_In_Align();
    }

    int Decoding() {
        if (frameOn && count > 0) {
            int i = 0, j = 0;
            for (; i <= count; i++) {
                DataIn[j++] = FrameIn[i];
            }
            frameOn = false;
            count = 0;
            return j;
        } else {
            return 0;
        }
    }

    int Encoding() {
        return 0;
    }

    synchronized int GetData(byte[] in_buf) {
        int bytes = 0;
        GetFrame();
        if (frameOn)                                        /*有数据*/ {
            bytes = count + 1;
            for (int i = 0; i < bytes; i++) {
                in_buf[i] = FrameIn[i];
            }
            frameOn = false;
            count = 0;
            judge = false;
        }
        return bytes;
    }

//int COM4_Buf::InDataProc(UCHAR *in_buf)
//{
//     GetFrame();
//     Decoding();
//     return 0;
//}

    int PutFrame() {
        int bytes;
        bytes = Encoding();
        for (int i = 0; i < bytes; i++) {
            WriteOutBuf(FrameOut[i]);
        }
        pt_Out_Align();
        return 0;
    }

    int PutData(byte[] out_buf, int num) {
        for (int i = 0; i < num; i++) {
            DataOut[i] = out_buf[i];
        }
        return 0;
    }

    byte GetRcvFlag() {
        if (RcvOk) {
            return 0x06;
        } else {
            return 0x15;
        }
    }
}
